package common

import (
	"fmt"
	"gitee.com/wangyexin/my-tools/domains/outs"
	"os"
	"reflect"
	"time"

	"github.com/xuri/excelize/v2"
)

func GetFileList(path string) []string {
	var all_file []string
	finfo, _ := os.ReadDir(path)
	for _, info := range finfo {
		real_path := path + "/" + info.Name()
		if !info.IsDir() {
			all_file = append(all_file, real_path)
		}
	}
	return all_file
}

type meta struct {
	Key string
	Idx int
}

func GetExcel(file string, sheetName string) outs.Response {

	xlsx, err := excelize.OpenFile(file)
	if err != nil {
		return CheckErr(err)
	}

	if sheetName == "" {
		sheetMap := xlsx.GetSheetMap()
		if len(sheetMap) > 0 {
			sheetName = sheetMap[1]
		}
	}

	rows, err := xlsx.GetRows(sheetName)

	if err != nil {
		return CheckErr(err)
	}
	if len(rows) < 2 {
		return CheckErr(err)
	}

	colNum := len(rows[1])
	fmt.Println("col num:", colNum)
	metaList := make([]*meta, 0, colNum)
	dataList := make([]map[int]string, 0, len(rows)-1)

	for line, row := range rows {
		switch line {
		case 0: // sheet 名
			for idx, colname := range row {
				fmt.Println(idx, colname, len(metaList))

				metaList = append(metaList, &meta{Key: colname, Idx: idx})
			}
		default: //>= 1 row data
			data := make(map[int]string, colNum)
			for k := 0; k < colNum; k++ {
				if k < len(row) {
					data[k] = row[k]
				}
			}

			dataList = append(dataList, data)
		}
	}

	return outs.OkWithData(toList(dataList, metaList))

}

func toList(datarows []map[int]string, metalist []*meta) []map[string]any {
	var data []map[string]any
	for _, row := range datarows {
		var mdata = make(map[string]any)
		for _, meta := range metalist {
			mdata[meta.Key] = row[meta.Idx]
		}
		data = append(data, mdata)
	}
	return data
}

// ExportExcelByMap 导出excel 数据源为[]map
func ExportExcelByMap(data []map[string]any, fileName, sheetName string) error {
	f := excelize.NewFile()
	sw, err := f.NewStreamWriter("Sheet1")
	f.SetSheetName("Sheet1", sheetName)
	if err != nil {
		fmt.Println(err)
		return err
	}

	rowNum := 1
	var dataSlice []any
	for key := range data[rowNum] {
		dataSlice = append(dataSlice, key)
	}
	_ = sw.SetRow("A1", dataSlice, excelize.RowOpts{Height: 30, Hidden: false})
	for _, value := range data {
		row := make([]any, 0)
		for _, v := range dataSlice {
			if val, ok := value[v.(string)]; ok {
				row = append(row, val)
			}
		}
		rowNum++
		if cell, err := excelize.CoordinatesToCellName(1, rowNum); err == nil {
			if err := sw.SetRow(cell, row); err != nil {
				return err
			}
		} else {
			return err
		}
	}
	if err := sw.Flush(); err != nil {
		fmt.Println(err)
		return err
	}
	return f.SaveAs(fileName)
}

// ExportExcelByStruct 导出excel 数据源为[]Struct
func ExportExcelByStruct[T any](datas []T, fileName, sheetName string) error {
	f := excelize.NewFile()
	headers := make([]any, 0)
	t := reflect.TypeOf(datas[0])
	if t.Kind() != reflect.Struct {
		return fmt.Errorf("data 数据格式不正确")
	}
	fieldNum := t.NumField()
	for i := 0; i < fieldNum; i++ {
		name := t.Field(i).Tag.Get("name")
		if name != "" {
			headers = append(headers, name)
		} else {
			headers = append(headers, t.Field(i).Name)
		}

	}
	sw, _ := f.NewStreamWriter("Sheet1")
	f.SetSheetName("Sheet1", sheetName)
	_ = sw.SetRow("A1", headers, excelize.RowOpts{Height: 20, Hidden: false})
	rowNum := 1
	for _, data := range datas {
		row := make([]any, 0)
		fieldNum := t.NumField()
		for i := 0; i < fieldNum; i++ {
			t := reflect.TypeOf(data)
			v := reflect.ValueOf(data)
			field := v.Field(i)
			switch field.Type().String() {
			case "time.Time":
				timeVal := field.Interface().(time.Time)
				val := timeVal.Format("2006-01-02 15:04:05")
				dateFormat := t.Field(i).Tag.Get("dateFormat")
				if dateFormat != "" {
					val = timeVal.Format(dateFormat)
				}
				if val == "0001-01-01 00:00:00" {
					val = ""
				}
				row = append(row, val)
			default:
				row = append(row, field.Interface())
			}
		}
		rowNum++
		if cell, err := excelize.CoordinatesToCellName(1, rowNum); err == nil {
			if err := sw.SetRow(cell, row); err != nil {
				return err
			}
		} else {
			fmt.Println(err)
			return err
		}
	}
	if err := sw.Flush(); err != nil {
		fmt.Println(err)
		return err
	}
	return f.SaveAs(fileName)
}

// Letter 遍历a-z
func Letter(length int) []string {
	var str []string
	for i := 0; i < length; i++ {
		str = append(str, string(rune('A'+i)))
	}
	return str
}
